
/***************************************************************************
 *   Copyright (C) 2006-2007 by Marco Martin                               *
 *   notmart@gmail.com                                                     *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the Lesser GNU General Public                   *
 *   License as published by the Free Software Foundation;                 *
 *   either version 2 of the License, or (at your option)                  *
 *   any later version.                                                    *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <klocale.h>
#include <kmessagebox.h>
#include <kuser.h>
#include <kstandarddirs.h>
#include <kmimetype.h>
#include <qfocusdata.h>
#include <qstyle.h>
#include <qfile.h>
#include <qcursor.h>
#include <kpopupmenu.h>
#include <kdebug.h>


#include "menuhandler.h"
#include "buttons.h"

MenuHandler::MenuHandler( QWidget *parent, Prefs *prefs, char *name, WFlags fl)
  :QFrame(parent, name, fl ), searchMode(false)
{

  prefSkel = prefs;

  //make a KServiceGroup to iterate the menu entries
  KServiceGroup::Ptr service = KServiceGroup::root();

  //Kicker config
  QString kickerConfPath = locate("config", "kickerrc");
  kickerConf = new KConfig(kickerConfPath);

  kickerConfWatch = new KDirWatch( this );
  kickerConfWatch->addFile(kickerConfPath);
  connect( kickerConfWatch, SIGNAL(dirty(const QString&)),   this,
           SLOT(slotModKickerConf()) );
  connect( kickerConfWatch, SIGNAL(dirty(const QString&)),   this,
           SIGNAL(kickerConfChanged()) );

  if( _newAppsNotification = prefSkel->newAppsNotification() )
  {
    //init the old and new installed list
    oldInstalledList = prefSkel->oldInstalledApps();
    loadNewInstalledApps();
    initOldInstalledApps(service);
    //save the creation time
    prefSkel->setOldInstalledAppsAge(time(0));
    initNewInstalledApps(service);
    if( newInstalledList.count() > 0 )
      emit(newApplications(newInstalledList.count()));
    prefSkel->setOldInstalledApps(oldInstalledList);
    prefSkel->setNewInstalledApps( newInstalledList );
    prefSkel->setNewInstalledAppsTimeStamps( newInstalledTimeStamps );
  }


  //Main widget initialization
  menu = new Menu(this, "tastyMenu");

  MenuHandlerLayout =  new QVBoxLayout( this, 0, 0, "MenuHandlerLayout"); 
  MenuHandlerLayout->addWidget(menu);

  readConfig();
  setupColumns();

  //Searchline...
  iconLoader = KGlobal::iconLoader();
  QPixmap icon;
  if( QApplication::reverseLayout() )
    icon = iconLoader->loadIcon("locationbar_erase", KIcon::Small);
  else
    icon = iconLoader->loadIcon("clear_left", KIcon::Small);
  menu->clearButton->setIconSet(icon);

  connect(menu->clearButton, SIGNAL(clicked()), menu->searchLine, SLOT (clear()) );

  menu->detachButton->setIconSet(QPixmap(uic_findImage("detach.png")));
  connect(menu->detachButton, SIGNAL(clicked()), this, SLOT (switchWindowMode()) );

  menu->searchLine->setContextMenuEnabled(false);

  //event filters for keyboard navigation
  menu->clearButton->installEventFilter(this);
  menu->searchLine->installEventFilter(this);
  menu->menuModes->installEventFilter(this);
  menu->runButton->installEventFilter(this);
  menu->switchButton->installEventFilter(this);
  menu->lockButton->installEventFilter(this);
  menu->logoutButton->installEventFilter(this);

  //action buttons
  icon = iconLoader->loadIcon("exit", KIcon::Toolbar);
  menu->logoutButton->setIconSet(icon);

  icon = iconLoader->loadIcon("lock", KIcon::Toolbar);
  menu->lockButton->setIconSet(icon);

  icon = iconLoader->loadIcon("run", KIcon::Toolbar);
  menu->runButton->setIconSet(icon);

  icon = iconLoader->loadIcon("locationbar_erase", KIcon::Toolbar);
  menu->clearRecentButton->setIconSet(icon);

  setCaption("Tasty Menu");
  setIcon(iconLoader->loadIcon("kmenu", KIcon::Panel));

  //user icon and login
  KUser *user = new KUser ();
  QString loginName (user->loginName ());
  QImage
    userImage (locate
               ("data", "/home/" + loginName + "/.face.icon"));
  if( !userImage.isNull() )
  {
    userImage = userImage.smoothScale (KIcon::SizeSmallMedium, KIcon::SizeSmallMedium);
    menu->switchButton->setIconSet(QPixmap(userImage));
  }
  menu->switchButton->setText(loginName);
  sessionsMenu = new QPopupMenu();
  menu->switchButton->setPopup(sessionsMenu);


  initializeRecentlyUsed( );

  populateList( service, menu->rootList, NULL, false );

  //left/middle mouse button
  connect (menu->dynamicList,
            SIGNAL (activated(QListViewItem *, const QPoint & , int  )), this,
            SLOT (dynListClicked(QListViewItem *, const QPoint &, int)));
  connect (menu->rootList,
           SIGNAL (activated(QListViewItem *, const QPoint & , int  )), this,
            SLOT (rootListClicked(QListViewItem *, const QPoint &, int)));
  connect (menu->childList,
           SIGNAL (activated(QListViewItem *, const QPoint & , int  )), this,
            SLOT (childListClicked(QListViewItem *, const QPoint &, int)));

  //right mouse button
  connect (menu->dynamicList,
           SIGNAL (contextMenuRequested(QListViewItem *, const QPoint & , int  )), this,
           SLOT (slotContextMenu(QListViewItem *, const QPoint &, int)));
  connect (menu->rootList,
           SIGNAL (contextMenuRequested(QListViewItem *, const QPoint & , int  )), this,
           SLOT (slotContextMenu(QListViewItem *, const QPoint &, int)));
  connect (menu->childList,
           SIGNAL (contextMenuRequested(QListViewItem *, const QPoint & , int  )), this,
           SLOT (slotContextMenu(QListViewItem *, const QPoint &, int)));

  //don't open categories on mouseover on childlist
  //menu->childList->setEasyOpen( true );

  connect (menu->clearRecentButton, SIGNAL (clicked()), this, SLOT (clearDynList()));
  connect (menu->logoutButton, SIGNAL (clicked()), this, SLOT (doLogout()));
  connect (menu->lockButton, SIGNAL (clicked()), this, SLOT (doLock()));
  connect (menu->runButton, SIGNAL (clicked()), this, SLOT (runDialog()));

  connect( sessionsMenu, SIGNAL(aboutToShow()), SLOT(slotPopulateSessions()) );
  connect( sessionsMenu, SIGNAL(activated(int)), SLOT(slotSessionActivated(int)) );


  connect( menu->menuModes, SIGNAL(activated(int)), SLOT(menuModeChanged(int)) );
  menuModeChanged(_menuMode);
}


MenuHandler::~MenuHandler()
{
}

void MenuHandler::loadNewInstalledApps()
{
  //Notification for newly installed apps
  xdgMenuLister =  new KDirLister( );
  KStandardDirs *standardDir=new KStandardDirs();
  QStringList appDirs = standardDir->findDirs("xdgdata-apps", ".");
  firstListing = 0;
  for(QStringList::Iterator it = appDirs.begin(); it != appDirs.end(); ++it)
  {
    xdgMenuLister->openURL(*it, true);
    /*HACK: links to kde programs are often installed in a kde subdirectory
    of one of these, so i duplicate all the entries with entry+"kde/"*/
    QString appDirWithKde = (*it)+"kde/";
    if( QFile::exists(appDirWithKde) )
    {
      xdgMenuLister->openURL(appDirWithKde, true);
      firstListing++;
    }
  }

  firstListing += appDirs.count();
  connect( xdgMenuLister, SIGNAL(newItems(const KFileItemList &)),   this,
           SLOT(slotApplicationsAdded(const KFileItemList &)) );
  connect( xdgMenuLister, SIGNAL(deleteItem( KFileItem *)),   this,
           SLOT(slotApplicationRemoved()) );

  xdgMenuWatch = new KDirWatch(this);
  xdgMenuWatch->addFile(locateLocal("xdgconf-menu", "applications-kmenuedit.menu"));
  //connect with slotApplicationRemoved() because we need to wait a while...
  connect( xdgMenuWatch, SIGNAL(dirty(const QString&)),   this,
           SLOT(slotApplicationRemoved()) );

  newInstalledList = prefSkel->newInstalledApps();
  newInstalledTimeStamps = prefSkel->newInstalledAppsTimeStamps();

  //expire old apps
  for(uint i=0; i<newInstalledTimeStamps.count(); i++)
  {
    //127800 seconds = two days
    if(time(0) - (uint)newInstalledTimeStamps[i] > 127800 )
    {
      newInstalledTimeStamps.remove(newInstalledTimeStamps.at(i));
      newInstalledList.remove(newInstalledList.at(i));
    }
  }
}

void MenuHandler::setupColumns()
{
  menu->dynamicList->header()->hide();
  menu->dynamicList->setResizeMode(QListView::AllColumns);
  menu->dynamicList->addColumn("name");
  menu->dynamicList->setShowToolTips(true);
  menu->dynamicList->setSortColumn(-1);
  menu->dynamicList->header()->setResizeEnabled(false);
  menu->dynamicList->setHScrollBarMode(QScrollView::AlwaysOff);
  menu->dynamicList->setActionIconSize( _actionIconSize );
  menu->dynamicList->setRootIsDecorated( _showExpander );
  //manage drag'n drop
  menu->dynamicList->setAcceptDrops(true);
  menu->dynamicList->setDragEnabled(true);
  connect( menu->dynamicList, SIGNAL(moved()),
           this, SLOT(dynListElemMoved()) );

  menu->rootList->header()->hide();
  menu->rootList->setResizeMode(QListView::AllColumns);
  menu->rootList->addColumn("name");
  menu->rootList->setSortColumn(-1);
  menu->rootList->header()->setResizeEnabled(false);
  menu->rootList->setHScrollBarMode(QScrollView::AlwaysOff);
  menu->rootList->setHighLightGroups( false );
  menu->rootList->setActionIconSize( _actionIconSize );
  menu->rootList->setDragEnabled(true);

  menu->childList->header()->hide();
  menu->childList->setResizeMode(QListView::AllColumns);
  menu->childList->addColumn("name");
  menu->childList->setSortColumn(_alphabetical?0:-1);
  menu->childList->header()->setResizeEnabled(false);
  menu->childList->setHScrollBarMode(QScrollView::AlwaysOff);
  menu->childList->setActionIconSize( _actionIconSize );
  menu->childList->setRootIsDecorated( _showExpander );
  menu->childList->setDragEnabled(true);
}


void MenuHandler::dynListElemMoved( )
{
  //very stupid: iterate the entire list and rewrite the favouriteList
  favouriteList.clear();
  QListViewItemIterator it( menu->dynamicList );

  while ( it.current() )
  {
    TastyListViewItem *li = dynamic_cast<TastyListViewItem *>(it.current());

    if( !li )
      return;

    favouriteList.append( li->getDeskopEntryPath() );
    it++;
  }

  prefSkel->setFavouriteApps(favouriteList);
  prefSkel->writeConfig();
}


bool MenuHandler::eventFilter( QObject *o, QEvent * e )
{
  if ( e->type() == QEvent::KeyPress )
  {
    QKeyEvent *keyEvent = (QKeyEvent *)e;
    QFocusData *fData = focusData();
    fData->home();

    switch( keyEvent->key() )
    {

      case Qt::Key_Up:
        if( dynamic_cast<QComboBox *>(o) )
          return false;
        fData->prev()->setFocus();
        break;

      case Qt::Key_Down:
      {
        if( dynamic_cast<QComboBox *>(o) )
            return false;

        //this is a workaround in order to set the focus on the
        //right widget when the combobox is disabled
        QWidget *nextWidget = fData->next();
        if( nextWidget->isEnabled() )
          nextWidget->setFocus();
        else
          fData->next()->setFocus();
      }
        break;

      case Qt::Key_Right:
        if( dynamic_cast<KListViewSearchLine *>(o) )
          return false;
        fData->next()->setFocus();
        break;

      case Qt::Key_Left:
        if( dynamic_cast<KListViewSearchLine *>(o) )
          return false;
        fData->prev()->setFocus();
        break;

      case Qt::Key_Enter:
      case Qt::Key_Return:
      {
        //only filter enter on search line
        if( o != menu->searchLine )
          return false;

        QListViewItem *listItem = NULL;
        //execute the only list item when there is exactly one
        QListViewItemIterator it( menu->dynamicList,
                                  QListViewItemIterator::Visible);
        //listItem = it.current();
        int count = 0;
        //ensure the first level have only one result
        while ( it.current() )
        {
          if( it.current()->childCount() == 0 )
          {
            count++;
            listItem = it.current();
          }
          kdDebug() << "current: " << count << " " << it.current()->text(0);
          if( count > 1 )
            return false;
          it++;
        }

        if( listItem )
        {
          dynListClicked(listItem, QPoint(0,0), 0);
          menu->searchLine->clear();
        }

        break;
      }

      default:
        return false;
        break;
    }
    return true;
  }
  //for some reasons clicking with the right mouse button on the searchline everything crashes...
/*  else if( e->type() == QEvent::MouseButtonPress && o == menu->searchLine )
  {return true;
    QMouseEvent *mouseEvent = (QMouseEvent *)e;

    if( mouseEvent->button() != QMouseEvent::RightButton )
      return true;

    if( menu->searchLine->text().length() < 4 )
      return true;
    else
      return false;
  }*/
  else
    return false;
}


void MenuHandler::readConfig()
{
  _menuMode = prefSkel->menuMode();
  if( _menuMode < 0 )
    _menuMode = 0;
  menu->menuModes->setCurrentItem(_menuMode);

  _currentCategory = prefSkel->currentCategory();

  kickerConf->setGroup("menus");
  _numRecentEntries = kickerConf->readNumEntry("NumVisibleEntries", 5);

  _hideOneChild = prefSkel->hideOneChild();
  _alphabetical = prefSkel->alphabetical();

  favouriteList = prefSkel->favouriteApps();
  if( favouriteList.isEmpty() )
  {
    favouriteList.append(locate("xdgdata-apps","kde/konqbrowser.desktop"));
    favouriteList.append(locate("xdgdata-apps","kde/KMail.desktop"));
    favouriteList.append(locate("xdgdata-apps","kde/Help.desktop"));
  }

  _showExpander = prefSkel->showExpander();
  _alwaysCollapsed = prefSkel->alwaysCollapsed();

  _displaySubText = prefSkel->displaySubText();

  _iconSize1 = prefSkel->iconSize1();
  if( _iconSize1 < 16 || _iconSize1 > 64 )
    _iconSize1 = 22;
  _iconSize2 = prefSkel->iconSize2();
  if( _iconSize2 < 16 || _iconSize2 > 64 )
    _iconSize2 = 22;
  _iconSize3 = prefSkel->iconSize3();
  if( _iconSize3 < 16 || _iconSize3 > 64 )
    _iconSize3 = 22;

  _actionIconSize = prefSkel->actionIconSize();
  if( _actionIconSize > _iconSize1 )
    _actionIconSize = _iconSize1;

  //menu size
  _menuWidth = 100.0/prefSkel->menuWidth();
  _menuHeight = 100.0/prefSkel->menuHeight();
  QRect r = QDesktopWidget().screenGeometry(this);
  int w = (int)(r.width()/_menuWidth);
  int h = (int)(r.height()/_menuHeight);
  resize(w,h);

  _kerryIntegration = prefSkel->kerryIntegration();
  _strigiIntegration = prefSkel->strigiIntegration();

  _isNormalWindow = prefSkel->isNormalWindow();
  if( _isNormalWindow )
  {
    menu->detachButton->setIconSet(QPixmap(uic_findImage("attach.png")));
    QToolTip::add( menu->detachButton, tr2i18n( "Make this window a popup menu" ) );
  }
  else
  {
    menu->detachButton->setIconSet(QPixmap(uic_findImage("detach.png")));
    QToolTip::add( menu->detachButton, tr2i18n( "Make this menu a normal window" ) );
  }

 // disconnect(menu->searchLine, 0, 0, 0);
  if( !_kerryIntegration && !_strigiIntegration )
  {
    //menu->searchLine->setListView((KListView *)(menu->dynamicList));
    disconnect(menu->searchLine, SIGNAL(returnPressed( const QString &)),
            this, SLOT (kerrySearch( const QString &)) );
    disconnect(menu->searchLine, SIGNAL(returnPressed( const QString &)),
            this, SLOT (strigiSearch( const QString &)) );
    connect(menu->searchLine, SIGNAL(textChanged( const QString &)),
            this, SLOT (initializeSearch( const QString &)) );
  }
  else if( _kerryIntegration )
  {
    menu->searchLine->setListView(NULL);
    menu->searchLine->setEnabled(true);
    disconnect(menu->searchLine, SIGNAL(textChanged( const QString &)),
            this, SLOT (initializeSearch( const QString &)) );
    disconnect(menu->searchLine, SIGNAL(returnPressed( const QString &)),
               this, SLOT (strigiSearch( const QString &)) );
    connect(menu->searchLine, SIGNAL(returnPressed( const QString &)),
            this, SLOT (kerrySearch( const QString &)) );
    menu->searchLine->setContextMenuEnabled(false);
  }
  else //strigi
  {
    menu->searchLine->setListView(NULL);
    menu->searchLine->setEnabled(true);
    disconnect(menu->searchLine, SIGNAL(textChanged( const QString &)),
               this, SLOT (initializeSearch( const QString &)) );
    disconnect(menu->searchLine, SIGNAL(returnPressed( const QString &)),
               this, SLOT (kerrySearch( const QString &)) );
    connect(menu->searchLine, SIGNAL(returnPressed( const QString &)),
            this, SLOT (strigiSearch( const QString &)) );
    menu->searchLine->setContextMenuEnabled(false);
  }
}

void MenuHandler::updateConfig()
{
  readConfig();

  menu->dynamicList->setActionIconSize( _actionIconSize );
  menu->rootList->setActionIconSize( _actionIconSize );
  menu->childList->setActionIconSize( _actionIconSize );

  menu->dynamicList->setRootIsDecorated( _showExpander );
  menu->childList->setRootIsDecorated( _showExpander );

  menuModeChanged( _menuMode );
  KServiceGroup::Ptr service = KServiceGroup::root();
  menu->rootList->clear();
    populateList( service, menu->rootList, NULL, false );
}


void MenuHandler::mousePressEvent( QMouseEvent *e)
{
  if(static_cast<QWidget *>(parent())->hasMouse())
  {
    close();
  }
  else if(!_isNormalWindow && !(rect().contains(e->pos())) )
  {
    hide();
    QTimer::singleShot(200, this,SLOT(close()));
  }
}

void MenuHandler::closeEvent ( QCloseEvent *e)
{
  e=e;

  if( _isNormalWindow )
  {
    prefSkel->setNormalWindowWidth(width());
    prefSkel->setNormalWindowHeight(height());
    prefSkel->setNormalWindowX(x());
    prefSkel->setNormalWindowY(y());
    prefSkel->writeConfig();
  }

  //HACK: I wait a little bit to permit closing the menu
  // when user clicks on the menu button again
  QTimer::singleShot(50, this, SLOT(hide()));
  emit(hidden());
}

void MenuHandler::popup(QPoint pos)
{
  if(isVisible())
  {
    close();
    return;
  }

  menu->searchLine->setFocus();

  int w;
  int h;
  if( !_isNormalWindow )
  {
    QRect r = QDesktopWidget().screenGeometry(this);
    w = (int)(r.width()/_menuWidth);
    h = (int)(r.height()/_menuHeight);
  }
  else
  {
    w = prefSkel->normalWindowWidth();
    h = prefSkel->normalWindowHeight();
  }

  //the only way to make things proportioned
  menu->leftFrame->setMaximumWidth( (int)((w-24)/3) );
  menu->allAppsFrame->setMaximumHeight(menu->clearButton->height());

  if( !_isNormalWindow )
    move(pos);
  else
    move(prefSkel->normalWindowX(), prefSkel->normalWindowY());

  resize(w,h);

  show();
}

void MenuHandler::initOldInstalledApps(KServiceGroup::Ptr group)
{
  if( !group || !group->isValid() )
    return;

  //expires at 639000 seconds = 10 days
  if( !prefSkel->oldInstalledApps().empty() ||
      (time(0) - (uint)prefSkel->oldInstalledAppsAge() < 639000 )
    )
    return;

  KServiceGroup::List list = group->entries(true, true, true, false);
  for (KServiceGroup::List::ConstIterator it = list.begin ();
       it != list.end (); it++)
  {
    KSycocaEntry *p = (*it);
    if( p->isType( KST_KServiceGroup ) )
    {
      KServiceGroup *g = static_cast < KServiceGroup * > ( p );
      if( g ->childCount() > 0 )
        initOldInstalledApps(g);
    }
    else
    {
      KService *s = static_cast < KService * >(p);

      oldInstalledList.append(s->desktopEntryPath());
    }
  }
}

void MenuHandler::initNewInstalledApps(KServiceGroup::Ptr group)
{
  if( !group || !group->isValid() )
    return;
  if( oldInstalledList.empty() )
    return;

  KServiceGroup::List list = group->entries(true, true, true, false);
  for (KServiceGroup::List::ConstIterator it = list.begin ();
       it != list.end (); it++)
  {
    KSycocaEntry *p = (*it);
    if( p->isType( KST_KServiceGroup ) )
    {
      KServiceGroup *g = static_cast < KServiceGroup * > ( p );
      if( g ->childCount()>0 )
        initNewInstalledApps(g);
    }
    else
    {
      KService *s = static_cast < KService * > ( p );


      QString path(s->desktopEntryPath());
      if( oldInstalledList.findIndex(path) == -1 &&
          newInstalledList.findIndex(path) == -1 )
      {
        newInstalledList.append(path);
        newInstalledTimeStamps.append(time(0));
        oldInstalledList.append(path);
      }
    }
  }
}


bool MenuHandler::searchNewItems(KServiceGroup::Ptr group)
{
  if( !group || !group->isValid() )
    return false;

  if( newInstalledList.count() <= 0 )
    return false;

  KServiceGroup::List list = group->entries(true, true, true, false);
  for (KServiceGroup::List::ConstIterator it = list.begin ();
       it != list.end (); it++)
  {
    KSycocaEntry *p = (*it);
    if( p->isType( KST_KServiceGroup ) )
    {
      KServiceGroup *g = static_cast < KServiceGroup * > ( p );
      if( g ->childCount()<=0 )
        continue;

      if(searchNewItems(g))
        return true;
    }
    else
    {
      KService *s = static_cast < KService * >(p);


      /*kdDebug() << group->relPath() << ": "<< s->desktopEntryPath()
                <<(( newInstalledList.findIndex(s->desktopEntryPath()) != -1 )
                   ?" present":" not present")<< endl;*/
      if( newInstalledList.findIndex(s->desktopEntryPath()) != -1 )
        return true;
    }
  }

  return false;
}

/*KServiceGroup::List MenuHandler::getServiceGroupList( KServiceGroup *serviceGroup )
{
  QString key(serviceGroup->directoryEntryPath());

  if( sListMap.contains(key) )
    return sListMap[key];
  else
  {
    KServiceGroup::List list = serviceGroup->entries(true, true, true, false);
    sListMap[key] = list;
    return list;
  }
}*/

void MenuHandler::populateList( KServiceGroup *serviceGroup, TastyListView *listView,
                                TastyListViewItem *listItemFather,
                                bool recursive, const QString & query )
{
  if( !serviceGroup || !serviceGroup->isValid() )
    return;
  serviceGroup->setShowEmptyMenu(false);
  //KServiceGroup::List list = serviceGroup->entries(true, true, true, false);

  KServiceGroup::List list = serviceGroup->entries(true, true, true, false);

  TastyListViewItem *prevListItem = NULL;

 for (KServiceGroup::List::ConstIterator it = list.begin ();
       it != list.end (); it++)
  {
      KSycocaEntry *p = (*it);

      int iconSize;
      if( listView && listView == menu->rootList
          || listItemFather && listItemFather->listView() == menu->rootList )
        iconSize = _iconSize2;
      else if( listView && listView == menu->childList
               || listItemFather && listItemFather->listView() == menu->childList)
        iconSize = _iconSize3;
      else
        iconSize = _iconSize1;

      if( p->isType( KST_KServiceGroup ) )
      {
         //KServiceGroup::Ptr g (static_cast < KServiceGroup * >(p));
         KServiceGroup *g = static_cast < KServiceGroup * > ( p );
         if( g ->childCount()<=0 || (g->name().at(0) == '.') )
           continue;

         g->setShowEmptyMenu(false);

         int numChilds = g->childCount();
         //FIXME: useless?
         if(numChilds == 0)
           continue;

         QPixmap iconPix = iconLoader->loadIcon(g->icon(), KIcon::Toolbar,iconSize);

         if ( iconPix.height () != iconSize)
         {
           QImage img = iconPix.convertToImage();
           if( !img.isNull() )
           {
             img = img.smoothScale ( iconSize, iconSize);
             iconPix = QPixmap (img);
           }
         }

         TastyListViewItem *listItem;
         if( listView )
           listItem = new TastyListViewItem( listView, prevListItem,
                                             !g->caption().isEmpty()?g->caption()
                                                      :g->name().section('/', -2));
         else
           listItem = new TastyListViewItem( listItemFather, prevListItem,
                                             !g->caption().isEmpty()?g->caption()
                                                      :g->name().section('/', -2));

         listItem->setPath( g->relPath() );
         listItem->setType( TastyListViewItem::ServiceGroup );
         //OpenGrup only on menu->rootList
         if( listView == menu->rootList )
           listItem->setActionType( TastyListViewItem::OpenGroup );
         else
           listItem->setActionType( TastyListViewItem::Collapse );

         prevListItem = listItem;

         listItem->setPixmap(0, iconPix);

         //avoiding to display empty categories or with only one child (very common in SUSE)
         if( (!_hideOneChild && numChilds > 0) || numChilds > 1 )
         {
            if( listView )
            {
              listView->insertItem( listItem  );
              if( _currentCategory == listItem->text(0) && listView == menu->rootList )
              {
                listView->setCurrentItem(listItem);
                listView->setOpenItem(static_cast<QListViewItem *>(listItem));
                rootListClicked(listItem, QPoint(0,0), 0);
              }
              if(searchNewItems(g))
                listItem->setHighLight(true);
            }
            else if(listItemFather)
              listItemFather->insertItem( listItem );

            if( recursive )
              populateList( g, NULL, listItem, true, query);

            //the left column is always open
            if( listView == menu->dynamicList ||
                (listItemFather && listItemFather->listView()==menu->dynamicList))
              listItem->setOpen( true );
            else
              listItem->setOpen( !_alwaysCollapsed );

            if( listItem->getActionType() == TastyListViewItem::Expand &&
                listItem->isOpen() )
              listItem->setActionType( TastyListViewItem::Collapse );
            else if( listItem->getActionType() == TastyListViewItem::Collapse &&
                     !listItem->isOpen() )
              listItem->setActionType( TastyListViewItem::Expand );
         }
         else if( recursive )
         {
           if( listView )
             populateList( g, listView, NULL, true, query);

           else if(listItemFather)
             populateList( g, NULL, listItemFather, true, query);

           delete listItem;
         }

      }
      else //The entry is a Service
      {
        KService *s = static_cast < KService * >(p);

        if( s->name().at(0) == '.' )
          continue;

        const bool isSeparator = s->name() == "separator";


        //Name and comment
        QString itemName = s->name();
        QString subText= QString();
        if( !isSeparator )
        {
          if( s->comment() != NULL && !s->comment().isEmpty() )
            subText = s->comment();
          else if( s->genericName() && !s->genericName().isEmpty() )
            subText = s->genericName();
        }

        //Have we done a query? (this improves query speed)
        if( query != NULL
            && !itemName.contains(query, false)
            && !subText.contains(query, false) )
          continue;

        TastyListViewItem *listItem;

        if( isSeparator )
        {
          if( _alphabetical )
            continue;

          if(listView)
          {
            listItem = new TastyListViewItem( listView, prevListItem, "separator" );
            listView->insertItem( listItem );
          }
          else if(listItemFather)
          {
            listItem = new TastyListViewItem( listItemFather, prevListItem, "separator" );
            listItemFather->insertItem( listItem );
          }
          else
            return;

          prevListItem = listItem;
          listItem->setSelectable(false);
          continue;
        }

        if( listView )
          listItem = new TastyListViewItem( listView, prevListItem, itemName );
        else
          listItem = new TastyListViewItem( listItemFather, prevListItem, itemName );

        listItem->setDisplaySubText(_displaySubText);
        listItem->setPath( serviceGroup->relPath() );
        listItem->setDeskopEntryPath( s->desktopEntryPath() );
        listItem->setMenuId( s->menuId() );
        listItem->setType( TastyListViewItem::Service );
        listItem->setActionType( TastyListViewItem::AddBookMark );

        listItem->setText(0,itemName);
        listItem->setSubText(subText);

        prevListItem = listItem;

        QPixmap iconPix = s->pixmap( KIcon::Toolbar, iconSize );
        if ( iconPix.height () != iconSize)
        {
          QImage img = iconPix.convertToImage();
          if( !img.isNull() )
          {
            img = img.smoothScale ( iconSize, iconSize);
            iconPix = QPixmap (img);
          }
        }
        listItem->setPixmap(0, iconPix);

         if( listView )
         {
           listView->insertItem( listItem );
         }
         else if(listItemFather)
         {
           listItemFather->insertItem( listItem );
         }
         if( newInstalledList.findIndex(s->desktopEntryPath()) != -1 )
           listItem->setHighLight(true);
      }

  }

}


void MenuHandler::initializeRecentlyUsed( )
{

  recentlyUsedMap.clear();
  moreUsedList.clear();

  kickerConf->reparseConfiguration();
  kickerConf->setGroup("menus");
  QStringList recentUsedList = QStringList::split(',',kickerConf->readEntry("RecentAppsStat"));

  for (QStringList::ConstIterator it = recentUsedList.begin();
        it != recentUsedList.end(); ++it )
  {
      QString item = (*it);

      QString desktopPath =  item.section(' ',2,2);
      if(desktopPath.isEmpty() || !QFile::exists(desktopPath))
        continue;

      recentlyUsedMap[-item.section(' ',1,1).toULong()] = desktopPath;
      moreUsedList.append(desktopPath);

  }

}

void MenuHandler::setupDynList( MenuMode mode )
{
   /*( mode == RecentDocuments
      || mode == MoreUsed
      || mode == RecentlyUsed )*/
  if( mode != Favourites )
    menu->clearRecentButton->show();
  else
    menu->clearRecentButton->hide();

  currentMenuMode = mode;
  menu->dynamicList->setAcceptDrops( mode == Favourites );
}

void MenuHandler::fillRecentDocuments( )
{
    menu->dynamicList->clear();
    setupDynList( RecentDocuments );

    QStringList recentDocsList = KRecentDocument::recentDocuments();

    TastyListViewItem *listItem = NULL;

    if( recentDocsList.isEmpty() )
     return;

    for (QStringList::Iterator it = recentDocsList.begin();
         it != recentDocsList.end(); ++it )
    {
        KDesktopFile *f= new KDesktopFile(*it, true /* read only */);

        if( !f )
          continue;

        listItem = new TastyListViewItem( menu->dynamicList, listItem, f->readName() );
        listItem->setMultiLinesEnabled(false);

        listItem->setDeskopEntryPath(*it);
        listItem->setType( TastyListViewItem::DesktopFile );

        QPixmap iconPix = iconLoader->loadIcon(f->readIcon(), KIcon::Panel, _iconSize1);
        if ( iconPix.height () > _iconSize1)
        {
          QImage img = iconPix.convertToImage();
          if( !img.isNull() )
          {
            img = img.smoothScale ( _iconSize1, _iconSize1);
            iconPix = QPixmap (img);
          }
        }
        listItem->setPixmap(0, iconPix);

        menu->dynamicList->insertItem( listItem );
    }

}


void MenuHandler::fillMoreUsed( )
{
    menu->dynamicList->clear();
    setupDynList( MoreUsed );

    int iteration = 0;

    TastyListViewItem *listItem = NULL;

    for (QStringList::Iterator it = moreUsedList.begin();
         it != moreUsedList.end(); ++it )
    {
        //FIXME: yeah, I know, this is U G L Y :-)
        if( iteration++ >= _numRecentEntries )
          break;

        KService::Ptr s = KService::serviceByDesktopPath(*it);
        if( !s )
          continue;

        listItem = new TastyListViewItem( menu->dynamicList, listItem, s->name());
        listItem->setSubText(!(s->comment().isEmpty())?s->comment():s->genericName() );

        listItem->setDeskopEntryPath( s->desktopEntryPath() );
        listItem->setType( TastyListViewItem::Service );
        listItem->setActionType( TastyListViewItem::AddBookMark );
        listItem->setDisplaySubText(_displaySubText);


        QPixmap iconPix = s->pixmap( KIcon::Toolbar, _iconSize1 );
        if( !iconPix.isNull() )
        {
          if ( iconPix.height () != _iconSize1)
          {
            QImage img = iconPix.convertToImage();
            if( !img.isNull() )
            {
              img = img.smoothScale ( _iconSize1, _iconSize1);
              iconPix = QPixmap (img);
            }
          }
          listItem->setPixmap(0, iconPix);
        }

        menu->dynamicList->insertItem( listItem );
    }

}

//FIXME: avoid the ugly code duplication
void MenuHandler::fillRecentlyUsed( )
{
    menu->dynamicList->clear();
    setupDynList( RecentlyUsed );

    int iteration = 0;
    TastyListViewItem *listItem = NULL;

    for (RecentlyUsedMap::Iterator it = recentlyUsedMap.begin();
         it != recentlyUsedMap.end(); ++it )
    {
        //FIXME: yeah, I know, this is U G L Y :-)
        if( iteration++ >= _numRecentEntries )
          break;

        KService::Ptr s = KService::serviceByDesktopPath(it.data());
        if( !s )
          continue;

        listItem = new TastyListViewItem( menu->dynamicList, listItem, s->name());
        listItem->setSubText(!(s->comment().isEmpty())?s->comment():s->genericName() );

        listItem->setDeskopEntryPath( s->desktopEntryPath() );
        listItem->setType( TastyListViewItem::Service );
        listItem->setActionType( TastyListViewItem::AddBookMark );
        listItem->setDisplaySubText(_displaySubText);


        QPixmap iconPix = s->pixmap( KIcon::Toolbar, _iconSize1 );
        if( !iconPix.isNull() )
        {
          if ( iconPix.height () != _iconSize1)
          {
            QImage img = iconPix.convertToImage();
            if( !img.isNull() )
            {
              img = img.smoothScale ( _iconSize1, _iconSize1);
              iconPix = QPixmap (img);
            }
          }
          listItem->setPixmap(0, iconPix);
        }

        menu->dynamicList->insertItem( listItem );
    }

}


//FIXME: avoid the ugly code duplication
void MenuHandler::fillFavourites( )
{
    menu->dynamicList->clear();
    setupDynList( Favourites );

    TastyListViewItem *listItem = NULL;

    for (QStringList::Iterator it = favouriteList.begin();
         it != favouriteList.end(); ++it )
    {

        KService::Ptr s = KService::serviceByDesktopPath(*it);
        if( !s )
          continue;
        listItem = new TastyListViewItem( menu->dynamicList, listItem, s->name());
        listItem->setSubText(!(s->comment().isEmpty())?s->comment():s->genericName() );

        listItem->setDeskopEntryPath( s->desktopEntryPath() );
        listItem->setType( TastyListViewItem::Service );
        listItem->setActionType( TastyListViewItem::RemoveBookMark );
        listItem->setDisplaySubText(_displaySubText);


        QPixmap iconPix = s->pixmap( KIcon::Toolbar, _iconSize1 );
        if ( iconPix.height () > _iconSize1)
        {
          QImage img = iconPix.convertToImage();
          if( !img.isNull() )
          {
            img = img.smoothScale ( _iconSize1, _iconSize1);
            iconPix = QPixmap (img);
          }
        }
        listItem->setPixmap(0, iconPix);

        menu->dynamicList->insertItem( listItem );
    }

}



void MenuHandler::slotModKickerConf()
{
  kickerConf->reparseConfiguration();
  initializeRecentlyUsed( );
  if( currentMenuMode == MoreUsed )
    fillMoreUsed();
  else if( currentMenuMode == RecentlyUsed )
    fillRecentlyUsed();
}


void MenuHandler::slotApplicationsAdded(const KFileItemList & newItems)
{

  if( firstListing > 0 )
  {
    firstListing--;
    return;
  }

  //avoiding to build a mammoth list...
  if( newItems.count() > 15 )
    return;

  for(KFileItemListIterator it(newItems); it.current(); ++it)
  {
    KFileItem *item = (*it);
    QString path(item->url().path());

    kdDebug() << "new item: " << item->name() << endl;
    //ignore items already here
    if( oldInstalledList.findIndex(path) == -1 )
    {
      newInstalledList.append(path);
      newInstalledTimeStamps.append( time(0) );
      oldInstalledList.append(path);
    }
  }

  prefSkel->setNewInstalledApps( newInstalledList );
  prefSkel->setNewInstalledAppsTimeStamps( newInstalledTimeStamps );
  prefSkel->setOldInstalledApps( oldInstalledList );

  emit(newApplications(newInstalledList.count()));

  //It's necessary to wait some seconds, otherwise apps won't be listed
  //I do it two times for being sure, because I still haven't the clear idea
  //where the right files to watch are...
  QTimer::singleShot(15000, this, SLOT(slotUpdateApplications()));
}


void MenuHandler::slotApplicationRemoved()
{
  QTimer::singleShot(15000, this, SLOT(slotUpdateApplications()));
  slotUpdateApplications();
}

void MenuHandler::slotUpdateApplications()
{
  KRun::runCommand ("kbuildsycoca");
  prefSkel->writeConfig();
  menu->rootList->clear();
  KServiceGroup::Ptr service = KServiceGroup::root();

  populateList( service, menu->rootList, NULL, false );
}

void MenuHandler::listClicked( TastyListViewItem * listItem, const QPoint & coord )
{
  if( !listItem )
    return;

  //exit if the user clicked on an empty area
  if( coord.y() != 0 &&
      (listItem->itemPos( )+ listItem->height()) < coord.y() )
    return;

  int x = coord.x();

  QString servicePath = listItem->getDeskopEntryPath();

  switch( listItem->getType() )
  {
    case TastyListViewItem::Service:
    {
      //These paranoid checks seems to be needed
      if( !listItem->listView() )
      return;
      TastyListView *lv = dynamic_cast<TastyListView *>(listItem->listView());
      if( !lv )
        return;
      if( x >= (lv->visibleWidth() - lv->getActionIconSpace()) )
      {
        switch( listItem->getActionType() )
        {
          case TastyListViewItem::AddBookMark:
            favouriteList.remove(servicePath);
            favouriteList.append(servicePath);
            prefSkel->setFavouriteApps(favouriteList);
            prefSkel->writeConfig();
            if( menu->menuModes->currentItem() == 0 )
              fillFavourites( );
            return;

          case TastyListViewItem::RemoveBookMark:
            favouriteList.remove(servicePath);
            prefSkel->setFavouriteApps(favouriteList);
            prefSkel->writeConfig();
            if( menu->menuModes->currentItem() == 0 )
              fillFavourites( );
            return;

          default:
            break;
        }
      }

      //if the item was highlighted get it back to normal and remove it from recently installed
      listItem->setHighLight(false);
      int index=newInstalledList.findIndex(servicePath);
      if( index != -1 )
      {
        newInstalledList.remove(newInstalledList.at(index));
        newInstalledTimeStamps.remove(newInstalledTimeStamps.at(index));
        prefSkel->setNewInstalledApps( newInstalledList );
        prefSkel->setNewInstalledAppsTimeStamps( newInstalledTimeStamps );
        emit(newApplications(newInstalledList.count()));
        //remove the highlight from the rootList, at the moment very costly
        slotUpdateApplications();
      }

      int started = KApplication::startServiceByDesktopPath( servicePath );
      if( !started )
      {
       DCOPRef kickerKMenuIface ("kicker", "KMenu");

       kickerKMenuIface.call("slotServiceStartedByStorageId(QString,QString)", "tastymenu", servicePath);
       if( (currentMenuMode == MoreUsed 
           || currentMenuMode == RecentlyUsed)
           && !searchMode)
         slotModKickerConf();
       if( !_isNormalWindow )
         close();
      }
      break;
    }

    case TastyListViewItem::ServiceGroup:
    {
      //open, collapse or expand?
      switch( listItem->getActionType() )
      {
        case TastyListViewItem::Expand:
          //avoiding setOpen when the user clicks on the three handle
          if( !listItem->xOnDecoration(x) )
            listItem->setOpen(true);
          if(listItem->isOpen())
            listItem->setActionType( TastyListViewItem::Collapse );
          break;
        case TastyListViewItem::Collapse:
          if( !listItem->xOnDecoration(x) )
            listItem->setOpen(false);
          if(!listItem->isOpen())
            listItem->setActionType( TastyListViewItem::Expand );
          break;
        case TastyListViewItem::OpenGroup:
        default:
        {
          KServiceGroup::Ptr serviceGroup = KServiceGroup::group( listItem->getPath() );
          if( serviceGroup )
          {
            menu->childList->clear();
            populateList( serviceGroup, menu->childList, NULL, true );
          }
          break;
        }
      }
      break;
    }

    case TastyListViewItem::DesktopFile:
    {
      KDEDesktopMimeType::run(servicePath, true);
      if( !_isNormalWindow )
        close();
      break;
    }

    default:
     return;
  }

}

void MenuHandler::dynListClicked( QListViewItem * listItem, const QPoint & coord, int c )
{
 c=c;
 if( !listItem )
   return;

 TastyListViewItem *tastyListItem = dynamic_cast<TastyListViewItem *>(listItem);
 if( !tastyListItem )
   return;

 listClicked( static_cast<TastyListViewItem *>(listItem), coord );
}

void MenuHandler::childListClicked( QListViewItem * listItem, const QPoint & coord, int c )
{
 c=c;
 if( !listItem )
   return;

 TastyListViewItem *tastyListItem = dynamic_cast<TastyListViewItem *>(listItem);
 if( !tastyListItem )
   return;

 /*if( _showExpander && (tastyListItem->getType() == TastyListViewItem::ServiceGroup) )
 {
   //FIXME: get the REAL size of the expander
   if( coord.x() > 16 )
     listItem->setOpen( !listItem->isOpen() );
 }
 else*/
   listClicked( static_cast<TastyListViewItem *>(listItem), coord );
}

void MenuHandler::rootListClicked( QListViewItem * listItem, const QPoint & coord, int c )
{
 c=c;
 if( !listItem )
   return;

 TastyListViewItem *tastyListItem = dynamic_cast<TastyListViewItem *>(listItem);
 if( !tastyListItem )
   return;

 //don't reload when the current category is clicked (except for the first run)
 if( menu->childList->childCount() > 0 &&
     prefSkel->currentCategory( ) == tastyListItem->text(0) )
   return;

 if( tastyListItem->getType() == TastyListViewItem::ServiceGroup )
 {
   prefSkel->setCurrentCategory( tastyListItem->text(0) );
   prefSkel->writeConfig();
 }

 listClicked( tastyListItem, coord );
 if( _alphabetical )
   menu->childList->setSorting(0);
}

void MenuHandler::slotContextMenu(QListViewItem *listItem, const QPoint &coord, int c)
{

  if( !listItem )
    return;
  TastyListViewItem *tastyListItem = dynamic_cast<TastyListViewItem *>(listItem);
  if( !tastyListItem )
    return;

  KPopupMenu menu(this);

  menu.insertTitle(tastyListItem->text(c));
  if( tastyListItem->getPath() != "" )
  {
    if( tastyListItem->getType() == TastyListViewItem::ServiceGroup )
      menu.insertItem(SmallIcon("kmenuedit"), i18n("&Edit submenu..."), 1);
    else if( tastyListItem->getType() == TastyListViewItem::Service )
    {
      menu.insertItem(SmallIcon("kmenuedit"), i18n("&Edit item..."), 1);
      menu.insertItem(SmallIcon("desktop"), i18n("&Add to desktop"), 3);
    }
  }

  if( tastyListItem->getActionType() == TastyListViewItem::AddBookMark )
    menu.insertItem(SmallIcon("bookmark_add"), i18n("&Add to favourite applications"), 2);
  else if( tastyListItem->getActionType() == TastyListViewItem::RemoveBookMark )
    menu.insertItem(SmallIcon("remove"), i18n("&Remove from favourite applications"), 2);

  int choice;
  if( menu.count() > 1 )
    choice = menu.exec(coord);
  else
    return;

  switch( choice )
  {
    case 1:
      KRun::runCommand ("kmenuedit /" + 
                        tastyListItem->getPath() +
                        " " +
                        tastyListItem->getMenuId());
      if( !_isNormalWindow )
        close();
      break;

    case 2:
      listClicked( tastyListItem, QPoint(tastyListItem->listView()->width(), 0) );
      break;

    case 3:
       KRun::runCommand( "cp " + tastyListItem->getDeskopEntryPath() + " ~/Desktop" );
      break;

    default:
      break;
  }

}

void MenuHandler::doLogout()
{
  close();
  DCOPRef kdesktopKDesktopIface ("kdesktop", "KDesktopIface");
  kdesktopKDesktopIface.call ("logout()");
}

void MenuHandler::doLock()
{
  hide();
  DCOPRef kdesktopKScreensaverIface ("kdesktop", "KScreensaverIface");
  kdesktopKScreensaverIface.call ("lock()");
  close();
}

void MenuHandler::runDialog()
{
  close();
  DCOPRef kdesktopKDesktopIface ("kdesktop", "KDesktopIface");
  kdesktopKDesktopIface.call ("popupExecuteCommand()");
}

/*Following functions are from official KDE Kmenu, Copyright 1996-2006 the kicker authors*/

void MenuHandler::slotPopulateSessions()
{
    int p = 0;
    DM dm;

    sessionsMenu->clear();

    sessionsMenu->insertItem(SmallIconSet("personal"), i18n("Edit user profile..."), 100 );
    sessionsMenu->insertSeparator();

    //optional save/restore session entries
    if(prefSkel->showSaveSession())
    {
      sessionsMenu->insertItem( i18n("Save current session"), 101 );
    }

    if (kapp->authorize("start_new_session") && (p = dm.numReserve()) >= 0)
    {
        if( kapp->authorize("lock_screen") )
          sessionsMenu->insertItem( i18n("Lock session and start a new one"), 102 );
        sessionsMenu->insertItem(SmallIconSet("fork"), i18n("Start New Session"), 103 );
        if (!p) {
            sessionsMenu->setItemEnabled( 101, false );
            sessionsMenu->setItemEnabled( 102, false );
        }
        sessionsMenu->insertSeparator();
    }

    SessList sess;
    if (dm.localSessions( sess ))
        for (SessList::ConstIterator it = sess.begin(); it != sess.end(); ++it) {
            int id = sessionsMenu->insertItem( DM::sess2Str( *it ), (*it).vt );
            if (!(*it).vt)
                sessionsMenu->setItemEnabled( id, false );
            if ((*it).self)
                sessionsMenu->setItemChecked( id, true );
        }
}

void MenuHandler::slotSessionActivated( int ent )
{
    close();

    switch(ent)
    {
      case 100:
        close();
        KRun::runCommand ("kcmshell kcm_useraccount");
        break;
      case 101:
      {
        close();
        DCOPRef ksmserverKsmserver ("ksmserver", "ksmserver");
        ksmserverKsmserver.call ("saveCurrentSession()");
        break;
      }
      case 102:
        doNewSession( true );
        break;
      case 103:
        doNewSession( false );
        break;
    }

    //switch on an other session
    if (!sessionsMenu->isItemChecked( ent ))
        DM().lockSwitchVT( ent );
}

void MenuHandler::doNewSession( bool lock )
{
    int result = KMessageBox::warningContinueCancel(
        kapp->desktop()->screen(kapp->desktop()->screenNumber(menu)),
        i18n("<p>You have chosen to open another desktop session.<br>"
               "The current session will be hidden "
               "and a new login screen will be displayed.<br>"
               "An F-key is assigned to each session; "
               "F%1 is usually assigned to the first session, "
               "F%2 to the second session and so on. "
               "You can switch between sessions by pressing "
               "Ctrl, Alt and the appropriate F-key at the same time. "
               "Additionally, the KDE Panel and Desktop menus have "
               "actions for switching between sessions.</p>")
                           .arg(7).arg(8),
        i18n("Warning - New Session"),
        KGuiItem(i18n("&Start New Session"), "fork"),
        ":confirmNewSession",
        KMessageBox::PlainCaption | KMessageBox::Notify);

    if (result==KMessageBox::Cancel)
        return;

    if (lock)
        doLock();

    DM().startReserve();
}


void MenuHandler::initializeSearch( const QString & query )
{
  if( !searchMode && query.length() > 2 )
   {
      if( !menu->searchLine->listView() )
        menu->searchLine->setListView((KListView *)(menu->dynamicList));
      searchMode = true;
      menu->menuModes->setEnabled(false);
      KServiceGroup::Ptr service = KServiceGroup::root();
      menu->dynamicList->clear();
      setCursor(QCursor(Qt::BusyCursor));
      populateList( service, menu->dynamicList, NULL, true, query );
      setCursor(QCursor(Qt::ArrowCursor));
   }
   else if( query.length() < 3  )
   {
      if( menu->searchLine->listView() )
      {
        menu->searchLine->setListView(NULL);
        menu->searchLine->setEnabled(true);
        menu->searchLine->setFocus();
        menu->searchLine->setContextMenuEnabled(false);
      }
      searchMode = false;
      menu->menuModes->setEnabled(true);
      menu->dynamicList->clear();
      menuModeChanged(_menuMode);
   }
}

void MenuHandler::kerrySearch( const QString & query )
{
  close();
  DCOPRef kdesktopKScreensaverIface ("kerry", "search");
  kdesktopKScreensaverIface.call ("search(QString)", query);
}

void MenuHandler::strigiSearch( const QString & query )
{
  close();
  KRun::runCommand ("konqueror strigi:/?q="+query);
}

void MenuHandler::clearDynList( )
{
  menu->dynamicList->clear();
  switch( currentMenuMode )
  {
    case MoreUsed:
    case RecentlyUsed:
    {
      DCOPRef kickerKMenuIface ("kicker", "kicker");
      kickerKMenuIface.call("clearQuickStartMenu()");
      slotModKickerConf();
      break;
    }
    case RecentDocuments:
      KRecentDocument::clear();
      break;
    default:
      break;
  }
}

void MenuHandler::menuModeChanged( int index )
{
 _menuMode = index;
 prefSkel->setMenuMode(_menuMode);

 switch(index)
 {
  case Favourites:
   fillFavourites();
   break;

  case MoreUsed:
   fillMoreUsed();
   break;

  case RecentlyUsed:
   fillRecentlyUsed();
   break;

  case RecentDocuments:
   fillRecentDocuments();
   break;

  default:
   break;
 }
}


void MenuHandler::switchWindowMode()
{
  if( !_isNormalWindow /*testWFlags(Qt::WType_Popup)*/ )
  {
    _isNormalWindow = true;
    hide();
    reparent(static_cast<QWidget *>(parent()),Qt::WType_Dialog, pos(), true);

    menu->detachButton->setIconSet(QPixmap(uic_findImage("attach.png")));
    prefSkel->setIsNormalWindow(true);
  }
  else
  {
    hide();
    reparent(static_cast<QWidget *>(parent()),
             Qt::WType_Popup|Qt::WNoAutoErase,
             pos(), true);

    menu->detachButton->setIconSet(QPixmap(uic_findImage("detach.png")));
    prefSkel->setIsNormalWindow(false);
    _isNormalWindow = false;
  }

  prefSkel->writeConfig();
}

//EOF
